home *** CD-ROM | disk | FTP | other *** search
/ The 640 MEG Shareware Studio 2 / The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO / pascal / pulldw.zip / PULLDOWN.PAS < prev    next >
Pascal/Delphi Source File  |  1987-12-04  |  18KB  |  743 lines

  1. unit pulldown;
  2.  
  3. {- contains menu and window routines }
  4. interface
  5. uses dos,crt;
  6. {$V-}
  7.  
  8.  
  9.  
  10. const
  11.      VIDSEG       : word    = $b000;
  12.      NOCURSOR               = $2000;
  13.      PLAINCURSOR  : word    = $0607;
  14.  
  15. var
  16.     ch:char;
  17.     oldtextattr : integer;
  18.  
  19. type str80    = string[80];
  20.      str30    = string[30];
  21.      anystr   = string[255];
  22.      windcoord=record
  23.                  wx,wy,wwid,wheight,wcolor : integer;
  24.                  lastx,lasty : integer;
  25.                 end;
  26.  
  27.      FKEYS = (UPKEY,DOWNKEY,LEFTKEY,RIGHTKEY,CR,HOMEKEY,ENDKEY,PGUPKEY,PGDNKEY,
  28.              ESCKEY,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,NOFKEY,TABKEY);
  29.  
  30.      savedwindow = array[1..2000] of byte;
  31.      strptr      = ^string;
  32.      FKEYSET     = set of FKEYS;
  33.  
  34. var
  35.    wind           : array[1..10] of windcoord;
  36.    fkey           : FKEYS;
  37.    choice,choice2 : integer;
  38.    savedwin       : array[1..5] of ^savedwindow;
  39.  
  40.  
  41. procedure SetCursor(Newcursor:word);
  42.  
  43. procedure MoveToScreen(Var Source,Dest; Length: Integer);
  44.  
  45. procedure MoveFromScreen(Var Source,Dest; Length: Integer);
  46.  
  47. procedure read_key(var ch:char; var key:FKEYS);
  48.  
  49. procedure field_str(X,Y,L:integer;attribute:byte; s:str80);
  50.  
  51. procedure get_field_str(X,Y,L:integer;var s:str80);
  52.  
  53. procedure field_attr(x,y,len,attr : integer);
  54.  
  55. procedure makewindow(num,x,y,wid,height,color:integer;
  56.                                     title:str80 );
  57.  
  58. procedure closewindow(num:integer);
  59.  
  60. procedure pulldownmenu(
  61.                  var txt1   : anystr;
  62.                  default,
  63.                  subdefault : integer;
  64.                  var choice,
  65.                  subchoice  : integer
  66.                                      );
  67.  
  68.  
  69.  
  70.  
  71. implementation
  72.  
  73. const
  74.   MENUFLOWTHRU : boolean = FALSE;
  75.  
  76. var
  77.   color, revcolor, bordercolor : integer;
  78.  
  79.  
  80. procedure InitDisplay;
  81. {
  82.   Initializes various global variables - must be called before using the
  83.   above procedures and functions.  If this is compiled as a UNIT, simply
  84.   place a call to InitDisplay before the 'end.'.
  85. }
  86.  
  87. var
  88.   Reg        : Registers;
  89.   colorcard  :boolean;
  90.  
  91. begin
  92.   Reg.AH := 15;
  93.   Intr($10, Reg);
  94.   ColorCard := Reg.AL <> 7;
  95.   if ColorCard then
  96.     VIDSEG := $B800
  97.   else
  98.     VIDSEG := $B000;
  99. end; { InitDisplay }
  100.  
  101. procedure SetCursor(Newcursor:word);
  102. var
  103.   Reg : Registers;
  104. begin
  105.   with Reg do
  106.   begin
  107.     AH := 1;
  108.     BH := 0;
  109.     CX := NewCursor;
  110.   end;
  111.   Intr($10, Reg);
  112. end;
  113.  
  114.  
  115. procedure MoveToScreen(Var Source,Dest; Length: Integer);
  116.  
  117.   Begin
  118.     If VIDSEG=$b000 Then Move(Source,Dest,Length)
  119.     Else
  120.      Begin
  121.       Length:=Length Shr 1;
  122.       Inline($1E/$55/$BA/$DA/$03/$C5/$B6/ Source /$C4/$BE/ Dest /$8B/$8E/
  123.              Length /$FC/$AD/$89/$C5/$B4/$09/$EC/$D0/$D8/$72/$FB/$FA/$EC/
  124.              $20/$E0/$74/$FB/$89/$E8/$AB/$FB/$E2/$EA/$5D/$1F);
  125.      End;
  126.   End;
  127.  
  128. procedure MoveFromScreen(Var Source,Dest; Length: Integer);
  129.   Begin
  130.     If VIDSEG=$b000 Then Move(Source,Dest,Length)
  131.     Else
  132.      Begin
  133.       Length:=Length Shr 1;
  134.       Inline($1E/$55/$BA/$DA/$03/$C5/$B6/ Source /$C4/$BE/ Dest /$8B/$8E/
  135.              Length /$FC/$EC/$D0/$D8/$72/$FB/$FA/$EC/$D0/$D8/$73/$FB/$AD/
  136.              $FB/$AB/$E2/$F0/$5D/$1F);
  137.      End;
  138.   End;
  139.  
  140.  
  141.  
  142.  
  143. procedure read_key(var ch:char; var key:FKEYS);
  144.  
  145. {
  146.   Returns a character in ch; or, if a function key was perssed, an FKEY
  147.   type in key
  148. }
  149.  
  150.  
  151. var cch : char;
  152.  
  153. begin
  154.   ch:=readkey;
  155.   case ch of
  156.    #13 : key := CR;
  157.    #9  : key := TABKEY;
  158.    #27 : if not(keypressed) then key := ESCKEY;
  159.    #0  :
  160.            begin
  161.              cch:=readkey;
  162.              case cch of
  163.                #72 : key := UPKEY;
  164.                #77 : key := RIGHTKEY;
  165.                #80 : key := DOWNKEY;
  166.                #75 : key := LEFTKEY;
  167.                #71 : key := HOMEKEY;
  168.                #79 : key := ENDKEY;
  169.                else  key := NOFKEY;
  170.              end;
  171.            end;
  172.    else key:=NOFKEY;
  173.   end;
  174. end;
  175.  
  176.  
  177.  
  178.  
  179.  
  180. procedure field_str(X,Y,L:integer;attribute:byte; s:str80);
  181.  
  182. {
  183.   Similar to Turbo Prolog's field_str predicate.  Displays a string at
  184.   coordinates x and y with a length of L.  If the string is shorter than
  185.   L, then it is padded with spaces.  Attribute determines the color.
  186. }
  187.  
  188. type
  189.   stc = record
  190.           ch  : char;
  191.           color : byte;
  192.         end;
  193.  
  194. var
  195.   I,J,L1     : Integer;
  196.   C          : Char;
  197.   stbuf      : array[1..80] of stc;
  198.   screen     : ^integer;
  199.  
  200. begin  {print}
  201.   L1:= Length(S);
  202.   J :=((Y-1)*160) + ((X-1)*2);      { compute starting location }
  203.   fillchar(stbuf,sizeof(stbuf),attribute);
  204.   screen := ptr(VIDSEG,j);
  205.   i := 1;
  206.   while i <= l do
  207.       begin
  208.         stbuf[ i ].ch := S[I];
  209.         inc(i);
  210.       end;
  211.  
  212.   while l1 < l do
  213.       begin
  214.         stbuf[l1+1].ch := ' ';
  215.         inc(L1);
  216.       end;
  217.   if l1>l then l1:=l;
  218.  
  219.   movetoscreen(stbuf[1],screen^,l1 * 2);
  220. end; { of print }
  221.  
  222.  
  223.  
  224.  
  225.  
  226. procedure get_field_str(X,Y,L:integer;var s:str80);
  227.  
  228. {
  229.   Like field_str above, but with a different flow-pattern: S is returned.
  230.  
  231. }
  232.  
  233. type
  234.   stc = record
  235.           ch  : char;
  236.           color : byte;
  237.         end;
  238.  
  239. var
  240.   I,J,L1     : Integer;
  241.   C          : Char;
  242.   stbuf      : array[1..80] of stc;
  243.   screen     : ^ integer;
  244.   s1         : str80 absolute s;
  245.  
  246. begin  {print}
  247.   J :=((Y-1)*160) + ((X-1)*2);      { compute starting location }
  248.   screen := ptr(VIDSEG,j);
  249.   movefromscreen(screen^,stbuf[1],l*2);
  250.   i := 1;
  251.   while i <= l do
  252.       begin
  253.         s1[i] := stbuf[i].ch;
  254.         inc(i);
  255.       end;
  256.   s1[0] := chr(l);
  257. end; { of print }
  258.  
  259.  
  260. procedure field_attr(x,y,len,attr : integer);
  261.  
  262. {
  263.   changes the attribute a a field on the screen
  264. }
  265.  
  266. var
  267.   s  : str80;
  268.  
  269. begin
  270.   get_field_str(x,y,len,S);
  271.   field_str(x,y,len,attr,s);
  272. end;
  273.  
  274.  
  275. procedure parse(var s, piece: anystr);
  276.  
  277. {
  278.   Only for parsing menu elements.  The parsing token is the '|' character.
  279.   CAUTION: This procedure takes the string 's', returns the first parsed part
  280.   in 'piece', and removes that piece from s.  S, therefore, is permanently
  281.   altered.
  282. }
  283.  
  284. var
  285.    ix,l : integer;
  286.  
  287. begin
  288.  while ( ord(s[0]) > 0 ) and ( s[1] = '|') do
  289.    delete(s,1,1);
  290.  
  291.  ix:=pos('|',s);
  292.  
  293.  if ix=0 then
  294.    begin
  295.      piece:=s;
  296.      s:='';
  297.    end
  298.  else
  299.    begin
  300.      piece := copy(s,1,ix-1);
  301.      delete(s,1,ix);
  302.    end;
  303. end;
  304.  
  305.  
  306.  
  307. procedure savewindow(num,x,y,wid,height:integer);
  308.  
  309. {
  310.   Saves on the heap the current contents of the screen defined by x,y,wid,
  311.   and height.
  312. }
  313.  
  314. var ix, i,start : integer;
  315. pointer : ^integer;
  316. size    : integer;
  317. s       : string[80];
  318.  
  319. begin
  320.   size := (wid+1) * (height+1) * 2;
  321.  
  322.   getmem(savedwin[num],size);
  323.   ix := 1;
  324.   for i := y to y+height do
  325.     begin
  326.       start:=((i-1)*160) + ((X-1)*2);
  327.       pointer := ptr(VIDSEG,start);
  328.       movefromscreen(pointer^ ,savedwin[num]^[ix],(wid+1)*2);
  329.       ix := ix + (wid+1) *2;
  330.     end;
  331.  
  332. end;
  333.  
  334.  
  335.  
  336.  
  337. procedure DrawBox(X,Y,Wid,Height,color: integer);
  338.  
  339.  
  340. var
  341.    I : integer;
  342.  
  343. begin
  344.       field_str(x,y,1,color,'┌');
  345.  
  346.       for i:= X+1 to X+Wid-1 do field_str(i,y,1,color,'─');
  347.       field_str(x+wid,y,1,color,'┐');
  348.  
  349.       for i:= Y+1 to Y+height-1 do
  350.         begin
  351.              field_str(x,i,1,color,'│');
  352.              field_str(x+wid,i,1,color,'│');
  353.         end;
  354.  
  355.        field_str(x,y+height,1,color,'└');
  356.        for i:= X+1 to X+Wid-1 do field_str(i,y+height,1,color,'─');
  357.        field_str(x+wid,y+height,1,color,'┘');
  358. end;
  359.  
  360. procedure makewindow(num,x,y,wid,height,color:integer;
  361.                                     title:str80 );
  362. {
  363.   Similar to the Turbo Prolog predicate of the same name.
  364. }
  365.  
  366. var
  367.   i,diff, newx : integer;
  368.   start,ix : integer;
  369.   pointer : ^integer;
  370.   oldattr:byte;
  371.  
  372. begin
  373.  
  374.   if wind[num].wx <> x then
  375.    begin
  376.     savewindow(num,x,y,wid,height);
  377.     drawbox(x,y,wid,height,bordercolor);
  378.     if length(title)>0 then
  379.       begin
  380.         diff:=wid-length(title);
  381.         newx:=x+diff div 2;
  382.         field_str(newx,y,length(title),bordercolor,title);
  383.       end;
  384.     window(x+1,y+1,x+wid-1,y+height-1);
  385. {   textattr:=color;   }
  386. {   clrscr;            }
  387. {   textattr:=oldattr; }
  388.  
  389.     for i:= 1 to height-1 do
  390.       field_str(x+1,y+i,wid-1,color,' ');
  391.  
  392.     with wind[num] do
  393.       begin
  394.        wx:=x;
  395.        wy:=y;
  396.        wwid:=wid;
  397.        wheight:=height;
  398.        wcolor:=color
  399.       end;
  400.    end;
  401. end;
  402.  
  403.  
  404.  
  405. procedure closewindow(num:integer);
  406. {
  407.   Closes a window previously created with number = 'num'.  Restores the
  408.   screen to its state previous to the window's creation. Releases heap memory
  409.   used to store this image.
  410. }
  411.  
  412. var ix, i,start : integer;
  413. pointer         : ^integer;
  414. size            : integer;
  415.  
  416. begin
  417.   with wind[num] do
  418.    if wx <> 0 then
  419.     begin
  420.       size := (wwid+1) * (wheight+1) * 2;
  421.       ix := 1;
  422.       for i := wy to wy+wheight do
  423.         begin
  424.           start:=((i-1)*160) + ((wx-1)*2);
  425.           pointer := ptr(VIDSEG,start);
  426.           movetoscreen(savedwin[num]^[ix],pointer^ ,(wwid+1)*2);
  427.           ix := ix + (wwid+1) * 2;
  428.         end;
  429.     end;
  430.   freemem(savedwin[num],size);
  431.   wind[num].wx := 0;
  432.   window(1,1,80,25);
  433. end;
  434.  
  435. procedure menu(num,x,y,color : integer;
  436.                title         : STR80;
  437.                txt1          : anystr;
  438.                default       : integer;
  439.                var choice    : integer;
  440.                var returnkey : FKEYS     );
  441.  
  442. {
  443.   Implements a popup menu defined by a string txt1 in the format:
  444.  
  445.   'choice1|choice2|....choiceN'
  446.  
  447.   The string must be <= 255 chars long.
  448. }
  449.  
  450. label
  451.   stop;
  452.  
  453. var
  454.   i,listlen,maxlen : integer;
  455.   dir              : FKEYS;
  456.   c                : char;
  457.   s,s1             : anystr;
  458.   txt              : array[1..20] of anystr;
  459.   term             : FKEYSET;
  460.  
  461. begin
  462.   if length(txt1)=1 then   { signals that no sub-menu is implemented here }
  463.     begin
  464.       choice    := 0;
  465.       returnkey := NOFKEY;
  466.       goto         stop;
  467.     end;
  468.  
  469.   {
  470.    If this menu is part of a pulldown system, then we want to exit when
  471.    LEFTKEY or RIGHTKEY are pressed; otherwise, only if enter of escape are
  472.    pressed.
  473.   }
  474.  
  475.   if MENUFLOWTHRU then term := [LEFTKEY,RIGHTKEY,CR,ESCKEY]
  476.    else term := [CR,ESCKEY];
  477.  
  478.   { paint picture of menu... }
  479.  
  480.   { parse s into choices and count them }
  481.   listlen:=0;
  482.   s:=txt1;
  483.   i:=1;
  484.   repeat
  485.     parse(s,s1);
  486.     txt[i]:=s1;
  487.     inc(i);
  488.   until (s = '') ;
  489.   listlen := i-1;
  490.  
  491.   { find the longest choice, so that the window may be properly sized... }
  492.   maxlen := 0;
  493.   for i:= 1 to listlen do
  494.     if length(txt[i]) > maxlen then maxlen := length(txt[i]);
  495.  
  496.   { ... present the choices }
  497.   if x + maxlen + 2 > 80 then x := 80-maxlen-2;
  498.   makewindow(num,x,y,maxlen+2,listlen+1,color,title);
  499.   for i:= 1 to listlen  do
  500.     field_str(x+1,y+i,maxlen+1,color,txt[i]);
  501.   choice := default;
  502.   repeat
  503.     field_str(x+1,y+choice,maxlen+1,revcolor,txt[choice]);
  504.     read_key(c,dir);
  505.     case dir of
  506.       UPKEY: begin
  507.                field_str(x+1,y+choice,maxlen+1,color,txt[choice]);
  508.                if choice = 1 then choice := listlen
  509.                  else dec(choice);
  510.              end;
  511.     DOWNKEY: begin
  512.                field_str(x+1,y+choice,maxlen+1,color,txt[choice]);
  513.                if choice = listlen then choice := 1
  514.                  else inc(choice);
  515.              end;
  516.    ESCKEY : if not MENUFLOWTHRU then choice := 0;
  517.    ENDKEY : begin
  518.             field_str(x+1,y+choice,maxlen+1,color,txt[choice]);
  519.             choice := listlen;
  520.             end;
  521.   HOMEKEY : begin
  522.             field_str(x+1,y+choice,maxlen+1,color,txt[choice]);
  523.             choice := 1;
  524.             end;
  525.    NOFKEY : begin { use first letter of choice }
  526.               c:=upcase(c);
  527.               i:=0;
  528.               repeat
  529.                 inc(i);
  530.               until(txt[i][1]=c) or (i=listlen);
  531.               if txt[i][1]=c then
  532.                 begin
  533.                   field_str(x+1,y+choice,maxlen+1,color,txt[choice]);
  534.                   choice:=i;
  535.                   dir:=CR;
  536.                   field_str(x+1,y+choice,maxlen+1,revcolor,txt[choice]);
  537.                 end;
  538.             end;
  539.  
  540.     end;
  541.   until (dir in term);
  542.   closewindow(num);
  543.   returnkey:=dir;
  544.   stop:
  545. end;
  546.  
  547.  
  548. procedure pulldownmenu(
  549.                  var txt1   : anystr;
  550.                  default,
  551.                  subdefault : integer;
  552.                  var choice,
  553.                  subchoice  : integer
  554.                                      );
  555. {
  556.   Implements a pulldown menu system
  557. }
  558.  
  559.  
  560. var
  561.   i,listlen,maxlen : integer;
  562.   dir              : FKEYS;
  563.   c                : char;
  564.   s,s1             : anystr;
  565.   txt              : array[1..10] of string[20];
  566.   txtpos           : array[1..10] of integer;
  567.   term             : FKEYSET;
  568.   top              : str80;
  569.   submen           : array[1..10] of strptr;
  570.   subline          : string;
  571.   cumlen           : integer;
  572.   rkey             : FKEYS;
  573.   items            : integer;
  574.  
  575. const
  576.   curchoice:array[1..10] of integer=(1,1,1,1,1,1,1,1,1,1);
  577.   { this allows us to return to the menu state in effect when the last
  578.     choice was made.
  579.   }
  580.   PULLEDDOWN :boolean = FALSE;
  581.  
  582. begin
  583.   term := [CR,ESCKEY];
  584.   setcursor(NOCURSOR);   { the cursor muddies up the menus }
  585.   (* paint picture of menu *)
  586.   listlen:=0;
  587.   s:=txt1; { assign to a local variable, since parsing destroys it }
  588.  
  589.   i:=1;
  590.   txtpos[1]:=1;
  591.   repeat
  592.     parse(s,s1);
  593.     txt[i]:=s1;
  594.     inc(i);
  595.   until (s = '') ;
  596.   listlen := i-1;
  597.  
  598.   for i:=2 to listlen do
  599.     txtpos[i]:= txtpos[i-1]+length(txt[i-1])+2;
  600.     { the positions of the choices on the bar menu }
  601.  
  602.   top := txt1;
  603.   cumlen:=length(txt1) + 1;
  604.  
  605.   { after getting and parsing the top line of the menu, get the strings
  606.     defining the pulldown menus.  These must be typed constants, as must
  607.     the top line, and they must be declared in order directly after the
  608.     declaration of the top line ( see the program's constant declaration
  609.     part, below.)  For top-menu items without a sub-menu (e.g., Edit, in
  610.     the Turbo Parcal menu) declare a string like this:
  611.  
  612.                      const
  613.                        s : string[1] = ' ';
  614.  
  615.   }
  616.  
  617.   for i := 1 to listlen do
  618.     begin
  619.       submen[i] := ptr(dseg,ofs(txt1)+cumlen);
  620.       { typed constants are in the data segment in ver. 4.0. If using ver.
  621.         3.0, try using 'cseg'
  622.       }
  623.       inc(cumlen,length(submen[i]^));
  624.       inc(cumlen);
  625.       {cumlen := cumlen + length(submen[i]^)+1;}
  626.     end;
  627.  
  628.  
  629.  
  630.  
  631.   gotoxy(1,1);
  632.   for i:= 1 to listlen  do
  633.     write(txt[i],'  ');
  634.  
  635.   choice := default;
  636.   subchoice := subdefault;
  637.  
  638.   MENUFLOWTHRU:=TRUE;  { force a return from menu for LEFTKEY or RIGHTKEY }
  639.   repeat
  640.     field_str(txtpos[choice],1,ord(txt[choice][0]),revcolor,txt[choice]);
  641.     subline:=submen[choice]^;
  642.     if (subline = ' ') or ( not PULLEDDOWN) then
  643.       read_key(c,dir)
  644.     else
  645.       menu(1,txtpos[choice],2,color,'',subline,
  646.              curchoice[choice],subchoice,dir);
  647.     case dir of
  648.    LEFTKEY: begin
  649.               field_str(txtpos[choice],1,ord(txt[choice][0]),color,txt[choice]);
  650.               curchoice[choice]:=subchoice;
  651.               if choice = 1 then choice := listlen
  652.                 else dec(choice);
  653.             end;
  654.   RIGHTKEY: begin
  655.               field_str(txtpos[choice],1,ord(txt[choice][0]),color,txt[choice]);
  656.               curchoice[choice]:=subchoice;
  657.               if choice = listlen then choice := 1
  658.                 else inc(choice);
  659.             end;
  660.    ESCKEY : if PULLEDDOWN and (subline <> ' ') then
  661.               begin
  662.                 PULLEDDOWN := FALSE;
  663.                 dir := NOFKEY;
  664.                 curchoice[choice] := subchoice;
  665.               end
  666.             else choice := 0;
  667.        CR : case PULLEDDOWN of
  668.             TRUE: if subline <> ' ' then
  669.                     curchoice[choice] := subchoice
  670.                   else curchoice[choice] := 1;
  671.             FALSE:if subline <> ' ' then
  672.                     begin
  673.                       PULLEDDOWN := TRUE;
  674.                       dir := NOFKEY;
  675.                     end;
  676.              end;
  677.    DOWNKEY: PULLEDDOWN := TRUE;
  678.    ENDKEY : begin
  679.               field_str(txtpos[choice],1,ord(txt[choice][0]),color,txt[choice]);
  680.               choice := listlen;
  681.             end;
  682.   HOMEKEY : begin
  683.               field_str(txtpos[choice],1,ord(txt[choice][0]),color,txt[choice]);
  684.               choice := 1;
  685.             end;
  686.    NOFKEY : begin
  687.               c:=upcase(c);
  688.               i:=0;
  689.               repeat
  690.                 inc(i);
  691.               until(txt[i][1]=c) or (i=listlen);
  692.               if txt[i][1]=c then
  693.                 begin
  694.                   field_str(txtpos[choice],1,ord(txt[choice][0]),color,txt[choice]);
  695.                   choice:=i;
  696.                   if submen[choice]^ = ' ' then dir:=CR
  697.                     else PULLEDDOWN := true;
  698.                   field_str(txtpos[choice],1,ord(txt[choice][0]),revcolor,txt[choice]);
  699.                 end;
  700.             end;
  701.  
  702.     end;
  703.   until (dir in term);
  704.   MENUFLOWTHRU:=FALSE;
  705.   setcursor(PLAINCURSOR);
  706. end;
  707.  
  708.  
  709.  
  710. procedure initmenus;
  711. {
  712.   Defines the colors to be used for the menu windows and frames.  There
  713.   is certainly a more direct way to do this.
  714.   If compiled as a unit, make a call to this procedure in the initialization
  715.   part.
  716. }
  717.  
  718. begin
  719.   fillchar(wind,sizeof(wind),0);
  720.   textcolor(lightgray);
  721.   textbackground(blue);
  722.   color := textattr;
  723.   if vidseg = $b800 then textcolor(blue)
  724.     else textcolor(black);
  725.   if vidseg = $b800 then textbackground(lightgray)
  726.     else textbackground(white);
  727.   revcolor := textattr;
  728.   textcolor(lightgray);
  729.   textbackground(black);
  730.   bordercolor:=textattr;
  731.   textattr:=color;
  732. end;
  733.  
  734.  
  735.  
  736. begin
  737.   oldtextattr := textattr;
  738.   initdisplay;
  739.   if VIDSEG =$B000 then PLAINCURSOR := $0B0C;
  740.   initmenus;
  741.   fillchar(wind,sizeof(wind),0);
  742.   choice := 1; choice2:=1;
  743. end.